package com.example.jooqdemo.config.jooq;

import com.alibaba.druid.pool.DruidDataSource;
import org.jooq.*;
import org.jooq.conf.Settings;
import org.jooq.impl.DataSourceConnectionProvider;
import org.jooq.impl.DefaultConfiguration;
import org.jooq.impl.DefaultDSLContext;
import org.jooq.impl.DefaultExecuteListenerProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

import javax.sql.DataSource;

@Configuration
public class JooqConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }

    @Bean
    public DataSourceConnectionProvider dataSourceConnectionProvider(
            @Qualifier("dataSource") DataSource dataSourceA) {
        return new DataSourceConnectionProvider(
                new TransactionAwareDataSourceProxy(dataSourceA));
    }

    @Bean
    public SpringTransactionProvider springTransactionProvider(
            @Qualifier("transactionManager") DataSourceTransactionManager txManager) {
        return new SpringTransactionProvider(txManager);
    }

    @Configuration
    public static class DslContextConfig {

        @Autowired(required = false)
        private RecordMapperProvider recordMapperProvider;

        @Autowired(required = false)
        private Settings settings;

        @Autowired(required = false)
        private RecordListenerProvider[] recordListenerProviders;

        @Autowired
        private ExecuteListenerProvider[] executeListenerProviders;

        @Autowired(required = false)
        private VisitListenerProvider[] visitListenerProviders;

        @Bean
        @Primary
        public DefaultDSLContext dslContext(@Qualifier(value = "dataSourceConnectionProvider") DataSourceConnectionProvider connectionProvider,
                                            @Qualifier("springTransactionProvider") SpringTransactionProvider springTransactionProvider) {
            return new DefaultDSLContext(configuration(connectionProvider, springTransactionProvider));
        }

        @Bean
        public JooqToSpringTransformer jooqToSpringTransformer() {
            return new JooqToSpringTransformer();
        }

        private DefaultConfiguration configuration(ConnectionProvider connectionProvider, TransactionProvider transactionProvider) {
            DefaultConfiguration configuration = new DefaultConfiguration();
            configuration.setSQLDialect(SQLDialect.MYSQL);
            configuration.set(connectionProvider);
            configuration.set(transactionProvider);
            configuration.set(new DefaultExecuteListenerProvider(
                    jooqToSpringTransformer()
            ));
            if (this.recordMapperProvider != null) {
                configuration.set(this.recordMapperProvider);
            }
            if (this.settings != null) {
                configuration.set(this.settings);
            }
            configuration.set(SQLDialect.MYSQL);
            configuration.set(this.recordListenerProviders);
            configuration.set(this.executeListenerProviders);
            configuration.set(this.visitListenerProviders);
            //配置执行监听器
            configuration.set(DefaultExecuteListenerProvider.providers(new SlowQueryListener()));
            return configuration;
        }
    }
}